package com.moyq5.wifi.joystick.fragment;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.fragment.app.Fragment;

import com.moyq5.wifi.joystick.Console;
import com.moyq5.wifi.joystick.NettyServerChannelFactory;
import com.moyq5.wifi.joystick.R;
import com.moyq5.wifi.joystick.ThreadKit;
import com.moyq5.wifi.joystick.command.P2pCommand;
import com.moyq5.wifi.joystick.command.P2pPassType;
import com.moyq5.wifi.joystick.command.impl.JoystickCommand;

public class JoystickFragment extends Fragment {

    private static final int OFFSET = 40;
    private boolean isFirstDown = true;

    private float initX;
    private float initY;

    private double btLeft;      // 按钮相对于容器左边距离
    private double btTop;       // 按钮相对于容器上边距离

    private double offsetX;      // 容器当前触模点相对于其中心点x偏移
    private double offsetY;      // 容器当前触模点相对于其中心点y偏移

    private JoystickCommand cmd = new JoystickCommand();

    private Console console;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_joystick, container, false);
        Button bt = view.findViewById(R.id.direction_bt);
        View btRang = (View)view.findViewById(R.id.direction_rang);
        btRang.setClickable(true);
        btRang.setOnTouchListener((v, e) -> {
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    v.performClick();
                    if (isFirstDown) {
                        isFirstDown = false;
                        initX = e.getX();
                        initY = e.getY();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:

                    offsetX = e.getX() - initX;
                    offsetY = e.getY() - initY;
                    btLeft = v.getPivotX() + offsetX;
                    btTop = v.getPivotY() + offsetY;

                    if (Math.pow(offsetX , 2) + Math.pow(offsetY, 2) > Math.pow((float)OFFSET/2, 2)) {
                        //Math.pow(xOffset, 2) + Math.pow(xOffset * offsetY/offsetX, 2) = Math.pow(OFFSET, 2);
                        //Math.pow((1 + offsetY/offsetX) * xOffset, 2) = Math.pow(OFFSET, 2);
                        double xOffset_ = Math.sqrt(Math.pow(OFFSET, 2)/(1 + Math.abs(offsetY/offsetX)));
                        double yOffset_ = xOffset_ * Math.abs(offsetY/offsetX);
                        if (xOffset_ > OFFSET) {
                            xOffset_ = OFFSET;
                        }
                        if (yOffset_ > OFFSET) {
                            yOffset_ = OFFSET;
                        }
                        if (offsetX < 0) {
                            btLeft = v.getPivotX() - xOffset_;
                        } else {
                            btLeft = v.getPivotX() + xOffset_;
                        }
                        if (offsetY < 0) {
                            btTop = v.getPivotY() - yOffset_;
                        } else {
                            btTop = v.getPivotY() + yOffset_;
                        }
                        offsetX = xOffset_;
                        offsetY = yOffset_;
                    }
                    if (btLeft < bt.getPivotX()
                            || btTop < bt.getPivotY()
                            || btLeft > v.getWidth() - bt.getPivotX()
                            || btTop > v.getHeight() - bt.getPivotY()) {
                        break;
                    }

                    bt.setX(Double.valueOf(btLeft - bt.getPivotX()).floatValue());
                    bt.setY(Double.valueOf(btTop - bt.getPivotY()).floatValue());

                    if (Math.tan(Math.PI/6) > Math.abs(offsetY)/Math.abs(offsetX)) {// 左右方向
                        if (v.getPivotX() > btLeft) {
                            cmd.setLeftBt(true);
                            //console("左");
                        } else {
                            cmd.setRightBt(true);
                            //console("右");
                        }
                    } else if (Math.tan(Math.PI/3) < Math.abs(offsetY)/Math.abs(offsetX)) {// 上下方向
                        if (v.getPivotY() > btTop) {
                            cmd.setUpBt(true);
                            //console("上");
                        } else {
                            cmd.setDownBt(true);
                            //console("下");
                        }
                    } else {
                        if (v.getPivotX() > btLeft && v.getPivotY() > btTop) {// 左上
                            cmd.setLeftBt(true);
                            cmd.setUpBt(true);
                            //console("左上");
                        } else if (v.getPivotX() > btLeft && v.getPivotY() < btTop) {// 左下
                            cmd.setLeftBt(true);
                            cmd.setDownBt(true);
                            //console("左下");
                        } else if (v.getPivotX() < btLeft && v.getPivotY() > btTop) {// 右上
                            cmd.setRightBt(true);
                            cmd.setUpBt(true);
                            //console("右上");
                        } else if (v.getPivotX() < btLeft && v.getPivotY() < btTop) {// 右下
                            cmd.setRightBt(true);
                            cmd.setDownBt(true);
                            //console("右下");
                        }
                    }

                    break;
                case MotionEvent.ACTION_UP:
                    bt.setX(v.getPivotX() - bt.getPivotX());
                    bt.setY(v.getPivotY() - bt.getPivotY());
                    break;
            }

            return false;
        });

        view.findViewById(R.id.a_bt).setOnClickListener(v -> {
            cmd.setaBt(true);
            //console("A");
        });
        view.findViewById(R.id.b_bt).setOnClickListener(v -> {
            cmd.setbBt(true);
            //console("B");
        });
        view.findViewById(R.id.c_bt).setOnClickListener(v -> {
            cmd.setcBt(true);
            //console("C");
        });
        view.findViewById(R.id.d_bt).setOnClickListener(v -> {
            cmd.setdBt(true);
            //console("D");
        });

        view.findViewById(R.id.a_bt).setOnTouchListener((v, e) -> {
            if (MotionEvent.ACTION_MOVE == e.getAction()) {
                cmd.setaBt(true);
                //console("AAA");
            }
            return true;
        });
        view.findViewById(R.id.b_bt).setOnTouchListener((v, e) -> {
            if (MotionEvent.ACTION_MOVE == e.getAction()) {
                cmd.setbBt(true);
                //console("BBB");
            }
            return true;
        });
        view.findViewById(R.id.c_bt).setOnTouchListener((v, e) -> {
            if (MotionEvent.ACTION_MOVE == e.getAction()) {
                cmd.setcBt(true);
                //console("CCC");
            }
            return true;
        });
        view.findViewById(R.id.d_bt).setOnTouchListener((v, e) -> {
            if (MotionEvent.ACTION_MOVE == e.getAction()) {
                cmd.setdBt(true);
                //console("DDD");
            }
            return true;
        });

        startCmdTask();

        return view;
    }

    private void console(String msg) {
        if (null != console) {
            console.debug(msg);
        }
    }

    private void startCmdTask() {
        ThreadKit.submit(() -> {
            String preCmd = "";
            while (!Thread.interrupted()) {
                if (!preCmd.equals((preCmd = cmd.toString()))) {
                    try {
                        NettyServerChannelFactory.getChannels().values().forEach(channel -> {
                            if (channel.isActive() && channel.isOpen() && channel.isWritable()) {
                                P2pCommand p2pCmd = new P2pCommand();
                                p2pCmd.setPassType(P2pPassType.SPI);
                                p2pCmd.setPassCommand(cmd);
                                JoystickCommand.raiseSerialNo();
                                P2pCommand.raiseSerialNo();
                                console.info(channel.remoteAddress() + "->>" + p2pCmd.format());
                                channel.writeAndFlush(p2pCmd.bytes());
                            }
                        });
                    } catch (Exception e) {
                        console.error(e, "消息发送异常");
                    }
                }
                cmd.reset();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ignored) {

                }
            }

        }, this);
    }

    public Console getConsole() {
        return console;
    }

    public void setConsole(Console console) {
        this.console = console;
    }

}